/*
This file is part of web3.js.

web3.js is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

web3.js is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with web3.js.  If not, see <http://www.gnu.org/licenses/>.
*/

import { Address, Uint } from './eth_types.js';
import { SupportedProviders } from './web3_base_provider.js';
import { Bytes, HexString } from './primitives_types.js';
import { EthExecutionAPI } from './apis/eth_execution_api.js';
import { AbiFragment, ContractAbi } from './eth_abi_types.js';

export interface ContractInitOptions {
	/**
	 * The maximum gas provided for a transaction (gas limit).
	 */
	readonly gas?: Uint;
	readonly gasLimit?: Uint;
	/**
	 * The gas price in wei to use for transactions.
	 */
	readonly gasPrice?: Uint;
	/**
	 * The address transactions should be made from
	 */
	readonly from?: Address;
	/**
	 * The byte code of the contract. Used when the contract gets {@link Contract.deploy | deployed}
	 */
	readonly data?: Bytes;
	readonly input?: Bytes;

	readonly provider?: SupportedProviders<EthExecutionAPI> | string;
	/**
	 * If `true`, the defaults of the contract instance will be updated automatically based on the changes of the context used to instantiate the contract.
	 */
	readonly syncWithContext?: boolean;

	readonly dataInputFill?: 'data' | 'input' | 'both';
	/**
	 * this will make calls default to `data`, `input` or `both`
	 */
}

export interface NonPayableCallOptions {
	nonce?: HexString;
	/**
	 * The address which is the call (the transaction) should be made from. For calls the `from` property is optional however it is
	 * highly recommended to explicitly set it or it may default to address(0) depending on your node or provider.
	 */
	from?: Address;
	/**
	 * The maximum gas (gas limit) provided for this call (this transaction)
	 */
	gas?: string;
	maxPriorityFeePerGas?: HexString;
	maxFeePerGas?: HexString;
	/**
	 * The gas price in wei to use for this call `transaction`.
	 */
	gasPrice?: string;
	type?: string | number;
	data?: HexString;
	input?: HexString;
}

export interface PayableCallOptions extends NonPayableCallOptions {
	/**
	 *
	 */
	value?: string;
}

export type ContractAbiWithSignature = ReadonlyArray<AbiFragment & { signature: HexString }>;

/**
 * Represents the options for a contract.
 */
export interface ContractOptions {
	/**
	 * The maximum gas provided for a transaction (gas limit).
	 */
	readonly gas?: Uint;

	/**
	 * The gas price in wei to use for transactions.
	 */
	readonly gasPrice?: Uint;

	/**
	 * The address transactions should be made from.
	 */
	readonly from?: Address;

	/**
	 * The byte code of the contract. Used when the contract gets {@link Contract.deploy | deployed}
	 */
	readonly input?: Bytes;

	/**
	 * The byte code of the contract. Used when the contract gets {@link Contract.deploy | deployed}
	 */
	readonly data?: Bytes;

	/**
	 * The {@doclink glossary#json-interface-abi | json interface} object derived from the [ABI](https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI) of this contract.
	 *
	 * Re-setting this will regenerate the methods and events of the contract instance.
	 *
	 * @example
	 * ```ts
	 * myContract.options.jsonInterface;
	 * > [{
	 *     "type":"function",
	 *     "name":"foo",
	 *     "inputs": [{"name":"a","type":"uint256"}],
	 *     "outputs": [{"name":"b","type":"address"}],
	 *     "signature": "0x...",
	 * },{
	 *     "type":"event",
	 *     "name":"Event",
	 *     "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}],
	 *     "signature": "0x...",
	 * }]
	 *
	 * // Set a new ABI interface
	 * // Note: the "signature" of every function and event's ABI is not needed to be provided when assigning.
	 * // It will be calculated and set automatically inside the setter.
	 * myContract.options.jsonInterface = [...];
	 * ```
	 */
	get jsonInterface(): ContractAbiWithSignature;
	set jsonInterface(value: ContractAbi);

	/**
	 * The address used for this contract instance. All transactions generated by web3.js from this contract will contain this address as the `to`.
	 *
	 * The address will be stored in lowercase.
	 *
	 * @example
	 * ```ts
	 * myContract.options.address;
	 * > '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae'
	 *
	 * // set a new address
	 * myContract.options.address = '0x1234FFDD...';
	 * ```
	 */
	address?: Address; // All transactions generated by web3.js from this contract will contain this address as the "to".

	/**
	 * The max priority fee per gas to use for transactions.
	 */
	maxPriorityFeePerGas?: Uint;

	/**
	 * The max fee per gas to use for transactions.
	 */
	maxFeePerGas?: Uint;
}
